<template>
  <el-drawer
    :title="title"
    v-model="visible"
    size="850px"
    :show-close="true"
    append-to-body
    destroy-on-close
	 :close-on-click-modal="false"
    @close="handleCloseDialog"
  >
    <template #default>
      <el-form
        ref="formRef"
        :model="formData"
        :rules="rules"
        class="drawer-form"
        label-width="100px"
		label-position="top"
      >
		<el-scrollbar >	
			<div class="section-title">
			  <span class="title-form_primary">基础信息</span>
			</div>
			<el-form-item prop="categoryId">
<!-- 			  <el-select v-model="formData.categoryId" placeholder="请选择类别">
				<el-option
				  v-for="item in categories"
				  :key="item.id"
				  :label="item.name"
				  :value="item.id"
				/>
			  </el-select> -->
			  
			  <el-tree-select
			    v-model="formData.categoryId" 
			    placeholder="请选择上级类别"
			    clearable
			    style="width: 100%"
			    :data="categories"
			    :props="{
			      value: 'id',
			      label: 'name',
			      children: 'children'
			    }"
			    check-strictly
			    :render-after-expand="false"
			    :filter-node-method="filterNode"
			  />
			  
			</el-form-item>
			<el-form-item prop="label">
			  <el-input v-model="formData.label" placeholder="请输入节点名称" />
			</el-form-item>
			<el-form-item prop="type">
			  <el-input v-model="formData.type" placeholder="请输入节点类型" />
			</el-form-item>
			
			<el-form-item prop="showHead">
			    <el-radio-group v-model="formData.showHead">
				  <el-radio :value="1">显示头部</el-radio>
				  <el-radio :value="0">隐藏头部{{}}</el-radio>
			    </el-radio-group>
			</el-form-item>
			
			<el-form-item prop="icon">
			  <icon-select v-model="formData.icon" />
			</el-form-item>
			<el-form-item prop="width">
			  <el-input-number v-model="formData.width" :min="0" />
			</el-form-item>
			<el-form-item prop="color">
			  <el-color-picker v-model="formData.color" />
			</el-form-item>
			<el-form-item prop="sort">
			  <el-input-number v-model="formData.sort" :min="0" />
			</el-form-item>
			<el-form-item prop="description">
			  <el-input v-model="formData.description" placeholder="请输入描述" type="textarea" maxlength="450" />
			</el-form-item>
			
			<div class="section-title">
			  <span class="title-form_primary">输入端口</span>
			</div>
			<div class="node-inputs-content">
			  <draggable
				v-model="formData.data.inputs"
				:animation="150"
				handle=".drag-handle"
				item-key="id"
				:component-data="{
				  tag: 'div',
				  type: 'transition-group',
				  name: !drag ? 'flip-list' : null
				}"
			  >
				<template #item="{ element, index }">
				  <div class="node-inputs-content-row">
					<el-button 
					  class="drag-handle" 
					  link
					>
					  <el-icon><Rank /></el-icon>
					</el-button>
					<div class="param-info">
					  <div class="param-name">{{ element.name || '-' }}</div>
					  <div class="param-detail">
						<span>类型: {{ element.type }}</span>
						<span>触发: {{ element.click=='1'?'是':'否' }}</span>
						<span v-if="['field','select','array'].includes(element.type)">输入类型: {{ element.fieldType }}</span>
					  </div>
					</div>
					<div class="param-actions">
					  <el-button 
						link
						type="primary" 
						@click="handleEditParam(index)"
					  >
						<el-icon><Edit /></el-icon>
					  </el-button>
					  <el-button 
						type="danger" 
						link 
						@click="removeInputParam(index)"
					  >
						<el-icon><Delete /></el-icon>
					  </el-button>
					</div>
				  </div>
				</template>
			  </draggable>
			  <div style="margin-bottom:18px;">
				<el-button type="primary" text @click="addInputParam">
				  <el-icon><Plus /></el-icon>添加输入端口
				</el-button>
			  </div>
			</div>
			<div class="section-title">
			  <span class="title-form_primary">输出端口</span>
			</div>
			<div class="node-inputs-content">
			  <draggable
				v-model="formData.data.outputs"
				:animation="150"
				handle=".drag-handle"
				item-key="id"
				:component-data="{
				  tag: 'div',
				  type: 'transition-group',
				  name: !drag ? 'flip-list' : null
				}"
			  >
				<template #item="{ element, index }">
				  <div class="node-inputs-content-row">
					<el-button 
					  class="drag-handle" 
					  link
					>
					  <el-icon><Rank /></el-icon>
					</el-button>
					<div class="param-info">
					  <div class="param-name">{{ element.name || '-'}}</div>
					  <div class="param-detail">
						  <span>类型: {{ element.type }}</span>
						  <span>触发: {{ element.click=='1'?'是':'否' }}</span>
						  <span v-if="['field','select','array'].includes(element.type)">输入类型: {{ element.fieldType }}</span>
					  </div>
					</div>
					<div class="param-actions">
					  <el-button 
						link
						type="primary" 
						@click="handleEditOutputParam(index)"
					  >
						<el-icon><Edit /></el-icon>
					  </el-button>
					  <el-button 
						type="danger" 
						link 
						@click="removeOutputParam(index)"
					  >
						<el-icon><Delete /></el-icon>
					  </el-button>
					</div>
				  </div>
				</template>
			  </draggable>
			  <div style="margin-bottom:18px;">
				<el-button type="primary" text @click="addOutputParam">
				  <el-icon><Plus /></el-icon>添加输出端口
				</el-button>
			  </div>
			</div>
		</el-scrollbar>
      </el-form>
    </template>
    <template #footer>
      <div class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="handleCloseDialog()">取 消</el-button>
      </div>
    </template>
	</el-drawer>
	
	<!-- 参数编辑弹窗 -->
	<param-form-dialog
	  v-model="paramDialog.visible"
	  :title="paramDialog.title"
	  :param="paramDialog.data"
	  @success="handleParamSuccess"
	/>
</template>

<script setup lang="ts">
import { ref, reactive, watch } from 'vue';
import type { FormInstance } from 'element-plus';
import { ElMessage } from 'element-plus';
import draggable from 'vuedraggable';
import type { BlueprintNodeForm, BlueprintNodeVO, BlueprintNodeCategoryVO } from '@/api/biz/blueprintnode';
import BlueprintNodeAPI from '@/api/biz/blueprintnode';
import { Rank, Edit } from '@element-plus/icons-vue';
import ParamFormDialog from './ParamFormDialog.vue';
import { v4 as uuidv4 } from 'uuid';

const components = {
  draggable,
  ParamFormDialog
};

const props = defineProps({
  modelValue: {
    type: Boolean,
    required: true
  },
  title: {
    type: String,
    required: true
  },
  node: {
    type: Object as () => BlueprintNodeVO,
    required: true
  },
  categories: {
    type: Array as () => BlueprintNodeCategoryVO[],
    required: true
  }
});

const emit = defineEmits(['update:modelValue', 'success']);

const visible = ref(false);
const formRef = ref<FormInstance>();
const drag = ref(false);

interface Field {
  id: string;
  name: string;
  code: string;
  type: string;
  value: string;
}

const formData = reactive<BlueprintNodeForm>({
  id: '',
  categoryId: '',
  label: '',
  type: '',
  icon: '',
  width: 200,
  color: '#1a3d1a',
  sort: 0,
  description: '',
  showHead:'1',
  data: {
    inputs: [] as Array<Field>,
    outputs: [] as Array<Field>
  }
});

const rules = {
  categoryId: [{ required: true, message: '请选择类别', trigger: 'change' }],
  label: [{ required: true, message: '请输入节点名称', trigger: 'blur' }],
  type: [{ required: true, message: '请输入节点类型', trigger: 'blur' }],
  icon: [{ required: true, message: '请输入图标名称', trigger: 'blur' }],
  width: [{ required: true, message: '请输入宽度', trigger: 'blur' }],
  color: [{ required: true, message: '请选择颜色', trigger: 'change' }],
  showHead: [{ required: true, message: '请选择是否隐藏头部', trigger: 'change' }],
  sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
};

const filterNode = (value: string, data: BlueprintNodeCategoryVO) => {
  if (!value) return true;
  return data.name.toLowerCase().includes(value.toLowerCase());
};

watch(() => props.modelValue, (val) => {
  visible.value = val;
});

watch(() => visible.value, (val) => {
  emit('update:modelValue', val);
});

const ensureDataExists = () => {
  if (!formData.data) {
    formData.data = {
      inputs: [],
      outputs: []
    };
  }
  if (!formData.data.inputs) {
    formData.data.inputs = [];
  }
  if (!formData.data.outputs) {
    formData.data.outputs = [];
  }
};

watch(
  () => props.node,
  (val) => {
    ensureDataExists();
    let nodeData = null;
    if (val.data) {
      try {
        nodeData = JSON.parse(val.data);
      } catch (e) {
        console.error('解析节点数据失败:', e);
        nodeData = {
          inputs: [],
          outputs: []
        };
      }
    }

    Object.assign(formData, {
      ...val,
      data: {
        inputs: Array.isArray(nodeData?.inputs) ? nodeData.inputs.map((item: Field) => ({ ...item })) : [],
        outputs: Array.isArray(nodeData?.outputs) ? nodeData.outputs.map((item: Field) => ({ ...item })) : []
      }
    });
  },
  { deep: true }
);

const submitForm = async () => {
  if (!formRef.value) return;
  await formRef.value.validate();
  
  ensureDataExists();
  await BlueprintNodeAPI.saveNode({
	id: formData.id,
	categoryId: formData.categoryId,
	label: formData.label,
	type: formData.type,
	icon: formData.icon,
	width: formData.width,
	color: formData.color,
	sort: formData.sort,
	description: formData.description,
	showHead: formData.showHead,
	data:JSON.stringify({
		inputs: formData.data.inputs,
		outputs:formData.data.outputs
	})
  });
  ElMessage.success('保存成功');
  handleCloseDialog();
  emit('success');
};

function resetForm() {
  formRef.value?.resetFields();
  formRef.value?.clearValidate();
  formData.id = "";
  formData.categoryId = "";
  formData.label = "";
  formData.type = "";
  formData.icon = "";
  formData.width = 200;
  formData.color = "#1a3d1a";
  formData.sort = 0;
  formData.description = "";
  formData.showHead = "1";
  formData.data = {
    inputs: [],
    outputs: []
  };
}

function handleCloseDialog() {
  visible.value = false;
  resetForm();
}

const paramDialog = reactive({
  visible: false,
  title: '',
  data: {} as Field,
  index: -1,
  isOutput: false
});

const addInputParam = () => {
  paramDialog.title = '新增输入参数';
  paramDialog.data = {
    id: uuidv4(),
    name: '',
    code: '',
    type: '',
    value: ''
  };
  paramDialog.index = -1;
  paramDialog.visible = true;
};

const handleEditParam = (index: number) => {
  ensureDataExists();
  paramDialog.title = '编辑输入参数';
  paramDialog.data = { ...formData.data.inputs[index] };
  paramDialog.index = index;
  paramDialog.visible = true;
};

const handleParamSuccess = (param: Field) => {
  ensureDataExists();

  if (paramDialog.isOutput) {
    if (paramDialog.index === -1) {
      formData.data.outputs.push(param);
    } else {
      formData.data.outputs[paramDialog.index] = param;
    }
  } else {
    if (paramDialog.index === -1) {
      formData.data.inputs.push(param);
    } else {
      formData.data.inputs[paramDialog.index] = param;
    }
  }
  paramDialog.visible = false;
  paramDialog.isOutput = false;
};

const removeInputParam = (index: number) => {
  ensureDataExists();
  formData.data.inputs.splice(index, 1);
};

const addOutputParam = () => {
  paramDialog.title = '新增输出参数';
  paramDialog.data = {
    id: uuidv4(),
    name: '',
    code: '',
    type: '',
    value: ''
  };
  paramDialog.index = -1;
  paramDialog.isOutput = true;
  paramDialog.visible = true;
};

const handleEditOutputParam = (index: number) => {
  ensureDataExists();
  paramDialog.title = '编辑输出参数';
  paramDialog.data = { ...formData.data.outputs[index] };
  paramDialog.index = index;
  paramDialog.isOutput = true;
  paramDialog.visible = true;
};

const removeOutputParam = (index: number) => {
  ensureDataExists();
  formData.data.outputs.splice(index, 1);
};

</script> 
<style lang="scss" scoped>
  .flip-list-move {
    transition: transform 0.5s;
  }
  .no-move {
    transition: transform 0s;
  }
  .ghost {
    opacity: 0.5;
    background: #c8ebfb;
  }

  .drawer-form {
    padding: 20px;
    height: calc(100vh - 130px);
    overflow-y: auto;
  }
  
  :deep(.el-drawer__header) {
    margin-bottom: 0;
    padding: 16px 20px;
    border-bottom: 1px solid var(--el-border-color-light);
  }
  
  :deep(.el-drawer__footer) {
    padding: 16px 20px;
    border-top: 1px solid var(--el-border-color-light);
    width: 100%;
  }
  
  :deep(.el-drawer__body) {
    padding: 0;
    height: calc(100% - 130px);
    overflow: hidden;
  }
  
  .node-inputs-content {
	padding-top: 18px;
	padding-left: 8px;
	padding-right: 8px;
	background-color: var(--el-fill-color-light);
	border-radius: 4px;
	margin-bottom: 20px;
    
    .node-inputs-content-row {
      display: flex;
      align-items: center;
      gap: 8px;
      margin-bottom: 8px;
      padding: 8px;
      background-color: var(--el-fill-color);
      border-radius: 4px;
      cursor: move;
      
      .drag-handle {
        cursor: move;
        color: var(--el-text-color-secondary);
        
        &:hover {
          color: var(--el-color-primary);
        }
        
        .el-icon {
          font-size: 16px;
        }
      }
      
      .param-info {
        flex: 1;
        margin: 0 12px;
        
        .param-name {
          font-weight: 500;
          margin-bottom: 4px;
        }
        
        .param-detail {
          font-size: 12px;
          color: var(--el-text-color-secondary);
          
          span {
            margin-right: 12px;
          }
        }
      }
      
      .param-actions {
        display: flex;
        gap: 4px;
      }
      
      .remove-btn {
        margin-top: 4px;
        margin-left: 4px;
        
        &:hover {
          color: var(--el-color-danger);
        }
      }
      
      &:hover {
        background-color: var(--el-fill-color-darker);
      }
    }
  }
  
  .dialog-footer {
    text-align: right;
  }
  
  .title-form_primary {
    font-style: normal;
    font-weight: 500;
    font-size: 14px;
    color: #1f2329;
    position: relative;
    padding-left: 5px;
  }
  .title-form_primary:before {
      content: "";
      width: 2px;
      height: 14px;
      background: var(--el-color-primary);
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      left: 0;
  }
</style>